package budget;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.StringTokenizer;

import event.Event;

import budget.Service.ServiceType;
import model.Model;

public class Budget extends Model{
	public Budget(long id, double adjustments, double totalWithoutAdjustment, Calendar lastDate, Request request, Collection<Service>services){
		super(id);
		this.adjustments = adjustments;
		this.totalWithoutAdjustment=totalWithoutAdjustment;
		this.lastDate = lastDate;
		this.request = request;
		this.services=new LinkedList<Service>(services);
	}
	public Budget(long id, Request request) {
		GregorianCalendar date = new GregorianCalendar();
		date.add(Calendar.DAY_OF_MONTH, 7);
		this.adjustments = 0;
		this.totalWithoutAdjustment=0;
		this.lastDate = date;
		this.request = request;
		this.services=new LinkedList<Service>();
	}
	
	public double getAdjustments() {
		return adjustments;
	}
	public double getTotalCostWhitoutAdjustment(){
		return this.totalWithoutAdjustment;
	}
	public double getTotal(){
		totalWithAdjustment = this.totalWithoutAdjustment+this.adjustments;
		return totalWithAdjustment;
	}
	public Collection<Service> getServices(){
		return this.services;
	}
	public void addService(Service service){
		this.services.add(service);
	}
	public void removeService(Service service){
		this.services.remove(service);
	}
	public void calculateTotalCostWhitoutAdjustment() throws Exception{
		Event e = this.getRequest().getEvent();
		int days = e.getDays();
		int guests = e.getGuestsNumber();
		double totalCost =0;
		double serviceCost = 0;
		double basePrice = 0;
		//Servizi aggiuntivi
		for(Service s: this.services){
			 serviceCost = s.getCost();
			if(s.isPerPerson())
				serviceCost = serviceCost * guests;
			if(s.isAtDay())
				serviceCost = serviceCost * days;
			totalCost += serviceCost;
		}
		
		//Tipo evento
		HashMap<String, Double> price = new HashMap<String, Double>();
		Scanner priceScanner;
		try {
			priceScanner = new Scanner(new File("priceList"));
			String key,value,line;
			while(priceScanner.hasNextLine()){
				line=priceScanner.nextLine();
				if(line.charAt(0)!='#'){
					StringTokenizer strTok=new StringTokenizer(line, ":");
					key=strTok.nextToken().trim().toUpperCase().replace(" ", "_");
					if(strTok.hasMoreTokens()) value=strTok.nextToken();
					else value="";
					price.put(key, Double.parseDouble(value));
				}
			}
		} catch (FileNotFoundException ex) {
			throw new Exception("MISSING_PRICELIST");
		} catch (NumberFormatException e2) {
			throw new Exception("CORRUPT_PRICELIST");
		}
		
		basePrice = price.get(e.getPreparationType().name())*price.get(e.getEventType().name()) *price.get(e.getServiceType().name())*guests*days;
		totalCost += basePrice;
		
		this.totalWithoutAdjustment = totalCost;
	}
	

	public void setAdjustments(double adj){
		this.adjustments = adj;
	}
	
	public Calendar getLastDate() {
		return lastDate;
	}
	public void setLastDate(Calendar lastDate) {
		this.lastDate =  lastDate;
	}
	public Request getRequest() {
		return request;
	}
	public void setRequest(Request request) {
		this.request = request;
	}
	
	public void setServices(Collection<Service> services) {
		this.services = new LinkedList<Service>(services);
	}
	public boolean canView(Service serv){
		if (serv.isOnlyOne()){
			if(serv.getServiceType()==ServiceType.OTHER){
				for(Service srv:services){
					if(serv.getName().equalsIgnoreCase(srv.getName()))
						return false;
				}
			}else{
				for(Service srv:services){
					if(serv.getServiceType()==srv.getServiceType())
						return false;
				}
			}
		}else
			if(serv.getServiceType()==ServiceType.OTHER){
				return true;
			}else{
				for(Service srv:services){
					if(serv.getName().equalsIgnoreCase(srv.getName()))
						return false;
				}
			}
		return true;
	}
	public Collection<Service> getVisibleServices(Collection<Service>allServices){
		ArrayList<Service> services=new ArrayList<Service>();
		for(Service srv:allServices)
			if(this.canView(srv))
				services.add(Service.clone(srv));
		return services;
	}
	public boolean contains(String filter){
		String string = adjustments +" "+ this.getId() +" "+ lastDate+" "+totalWithAdjustment;
		if(string.contains(filter) || request.contains(filter))
			return true;
		for(Service s : services)
			if(s.contains(filter))
				return true;
		return false;
	}
	
	private double totalWithAdjustment = 0;
	private double totalWithoutAdjustment = 0;
	private LinkedList<Service> services;
	private double adjustments;
	private Calendar lastDate;
	private Request request;
	
}
